//
//  AFNetWorkRequestTool.m
//  TBNetworking_Example
//
//  Created by apple on 2018/8/8.
//  Copyright © 2018年 lzb. All rights reserved.
//

#import "AFNetWorkRequestTool.h"
#if __has_include(<AFNetworking/AFNetworking.h>)
#import <AFNetworking/AFNetworking.h>
#else
#import "AFNetworking.h"
#endif

#import "AFExtensionDataConversion.h"

#import "ZBHTTPSessionManager.h"




static ZBHTTPSessionManager *_resquestManger;

@interface AFNetWorkRequestTool()

@property (nonatomic, strong) Class responseClass;

//是否需要解析
@property (nonatomic, assign) BOOL isRequireAnalysis;

//请求管理
@property (nonatomic, strong)  ZBHTTPSessionManager *sessionManger;

//请求队列
@property (nonatomic, strong)  dispatch_queue_t responseQueue;

/**
 失败默认Message
 */
@property (nonatomic, strong)  NSString *failDefaultMessage;

@end

@implementation AFNetWorkRequestTool

+ (AFNetWorkRequestTool *)shareInstance
{
    static AFNetWorkRequestTool *_instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc]init];
    });
    return _instance;
}
+ (ZBHTTPSessionManager *)shareResquestManger
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if(_resquestManger == nil)
            _resquestManger = [ZBHTTPSessionManager manager];
    
        //无条件的信任服务器上的证书
        AFSecurityPolicy *securityPolicy =[AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
        
        // 客户端是否信任非法证书
        securityPolicy.allowInvalidCertificates = YES;
        
        // 是否在证书域字段中验证域名
        securityPolicy.validatesDomainName = NO;
        
        _resquestManger.securityPolicy = securityPolicy;
    });
    return _resquestManger;
}

#pragma mark - 请求类
- (NSURLSessionDataTask *)httpRequestWithModel:(BaseResquestModel *)requestModel
                             ResponseClass:(Class)responseClass
                         isRequireAnalysis:(BOOL)isRequireAnalysis
                            sucessResponse:(sucessResponseBlock)sucessBlock
                              failResponse:(failResponseBlock)failBlock
{
   AFNetworkRequestMethod method = [self fetchRequestMethodWithRequest:requestModel];
    return [self httpRequestWithModel:requestModel ResponseClass:responseClass isRequireAnalysis:isRequireAnalysis requestMehtod:method sucessResponse:sucessBlock failResponse:failBlock];

}
- (NSURLSessionDataTask *)httpRequestWithModel:(BaseResquestModel *)requestModel
                                 ResponseClass:(Class)responseClass
                             isRequireAnalysis:(BOOL)isRequireAnalysis
                                 requestMehtod:(AFNetworkRequestMethod)method
                                sucessResponse:(sucessResponseBlock)sucessBlock
                                  failResponse:(failResponseBlock)failBlock
{
    [self handleRequesst:requestModel responseClass:responseClass];
    
    return [self httpRequestWithModel:requestModel ResponseClass:responseClass isRequireAnalysis:isRequireAnalysis requestMehtod:method uploadProgress:nil sucessResponse:sucessBlock failResponse:failBlock];
}
- (NSURLSessionDataTask *)httpRequestWithModel:(BaseResquestModel *)requestModel
                                 ResponseClass:(Class)responseClass
                             isRequireAnalysis:(BOOL)isRequireAnalysis
                                 requestMehtod:(AFNetworkRequestMethod)method
                                uploadProgress:(uploadProgressBlock)progressBlock
                                sucessResponse:(sucessResponseBlock)sucessBlock
                                  failResponse:(failResponseBlock)failBlock
{
    //1.获取请求的URL
    NSString *url =  [self fetctRequestUrl:requestModel];
    
    //2.获取请求参数
    NSDictionary *paramDict = [self fetchParamDictionaryWithRequest:requestModel];
    
    //3.创建请求任务
    NSURLSessionDataTask *task = [self httpBaseRequestWithURL:url parameters:paramDict isRequireAnalysis:isRequireAnalysis HTTPMethodType:method uploadProgress:progressBlock sucessResponse:sucessBlock failResponse:failBlock];
    
    return task;
}

#pragma mark - 请求处理
- (void)handleRequesst:(BaseResquestModel *)requestModel responseClass:(Class)responseClass
{
    _resquestModel = requestModel;
    self.responseClass = responseClass;

    //1.配置请求头
    AFHTTPRequestSerializer *requestSerializer = [self configSessionManagerRequestSerializerByRequest:requestModel];
    
    
    //2.配置响应头
    AFHTTPResponseSerializer *responseSerializer = [self configSessionManagerResonseSerializerByRequest:requestModel];
    
    //3.配置响应对列
    dispatch_queue_t queue = [self fetctResponsequeue:requestModel];
    self.responseQueue = queue;
    
    
   //4.获取默认请求失败文字
    self.failDefaultMessage = [self fetctFailDefaultMessage:requestModel];
    
    //5.开始配置
    ZBHTTPSessionManager *httpManger = [AFNetWorkRequestTool shareResquestManger];
    
    httpManger.completionQueue = queue;
    
    httpManger.requestSerializer = requestSerializer;
    
    httpManger.responseSerializer = responseSerializer;

    self.sessionManger = httpManger;
}
/**
 拼接URL
 */
- (NSString *)fetctRequestUrl:(BaseResquestModel<AFNetworkRequestConfigProtocol> *)request
{
    NSString *path = @"";
    if([request respondsToSelector:@selector(configRequestAPIURL)]){
        path = [request configRequestAPIURL];
    }
    
    if(path.length == 0){
        LZBLog(@"错误！URL不正确");
        return nil;
    }
    return path;
}


/**
 获取响应队列
 */
- (dispatch_queue_t)fetctResponsequeue:(BaseResquestModel<AFNetworkRequestConfigProtocol> *)request
{
    dispatch_queue_t queue;

    if([request respondsToSelector:@selector(configResponsequeue)]){
        queue = [request configResponsequeue];
    }
    
    if(queue == nil)
        queue = dispatch_get_main_queue();

    return queue;
}
/**
 获取响应队列
 */
- (NSString *)fetctFailDefaultMessage:(BaseResquestModel<AFNetworkRequestConfigProtocol> *)request
{
    NSString *message = @"";
    
    if([request respondsToSelector:@selector(configResponsequeue)]){
        message = [request configRequestFailDefaultMessage];
    }
    
    if(message.length == 0)
        message = AFNETWORK_DEFAULT_FAIL_MESSAGE;
    
    return message;
}

- (AFNetworkRequestMethod)fetchRequestMethodWithRequest:(BaseResquestModel<AFNetworkRequestConfigProtocol> *)request
{
    AFNetworkRequestMethod method =  AFNetworkRequestMethod_GET;
    if([request respondsToSelector:@selector(configRequestMethod)]){
        method = [request configRequestMethod];
    }
    return method;
}
/**
  拼接请求参数
 */
- (NSDictionary *)fetchParamDictionaryWithRequest:(BaseResquestModel<AFNetworkRequestConfigProtocol> *)request
{
    NSMutableDictionary *tempDict = [NSMutableDictionary dictionary];
   
    if([request respondsToSelector:@selector(configRequestParamDictionary)]){
        NSDictionary *dictData =  [request configRequestParamDictionary];
        //去除null
        NSMutableDictionary *paramDict = [dictData mutableCopy];
        NSArray *keysForNullValues = [paramDict allKeysForObject:[NSNull null]];
        [paramDict removeObjectsForKeys:keysForNullValues];
        if(paramDict != nil){
            [tempDict addEntriesFromDictionary:paramDict];
        }
    }
    if(tempDict.count == 0) return nil;
    
    return [NSDictionary dictionaryWithDictionary:tempDict];
}
/**
 配置请求头
 */
- (AFHTTPRequestSerializer *)configSessionManagerRequestSerializerByRequest:(BaseResquestModel<AFNetworkRequestConfigProtocol> *)request
{
    
    //1.配置请求序列化类型AFNetworkRequestSerializerType
    AFHTTPRequestSerializer *requestSerializer = [AFJSONRequestSerializer serializer];
    if([request respondsToSelector:@selector(configRequestSerializerType)]){
        AFNetworkRequestSerializerType type = [request configRequestSerializerType];
        if(type == AFNetworkRequestSerializerType_HTTP){
            requestSerializer =  [AFHTTPRequestSerializer serializer];
        }
        else if(type == AFNetworkRequestSerializerType_JSON){
            requestSerializer =  [AFJSONRequestSerializer serializer];
        }
    }
    
    //2.配置请求超时时间
    NSTimeInterval timeoutInterval = 30.0f;
    if([request respondsToSelector:@selector(configRequestTimeoutInterval)]){
        timeoutInterval = [request configRequestTimeoutInterval];
    }
    requestSerializer.timeoutInterval = timeoutInterval;
    
    
    //3.配置缓存策略
    NSURLRequestCachePolicy cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
    if([request respondsToSelector:@selector(confgiCachePolicy)]){
        NSURLRequestCachePolicy getcachePolicy = [request confgiCachePolicy];
        if(cachePolicy != getcachePolicy)
            cachePolicy = getcachePolicy;
    }
    requestSerializer.cachePolicy = cachePolicy;
    
    //3.同一配置请求头
    if([request respondsToSelector:@selector(configRequestHeaderFieldValueDictionary)])
    {
        NSDictionary<NSString *, NSString *> *headerFieldValueDictionary = [request configRequestHeaderFieldValueDictionary];
        if (headerFieldValueDictionary != nil) {
            [headerFieldValueDictionary enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
                if(key == nil || obj== nil) *stop = YES;
                [requestSerializer setValue:obj forHTTPHeaderField:key];
            }];
            
        }
    }
    return requestSerializer;
}

- (AFHTTPResponseSerializer *)configSessionManagerResonseSerializerByRequest:(BaseResquestModel<AFNetworkRequestConfigProtocol> *)request
{
    
    //1.配置响应序列化类型AFNetworkRequestSerializerType
    AFHTTPResponseSerializer *responseSerilizer = [AFJSONResponseSerializer serializer];
    if([request respondsToSelector:@selector(configResponseSerializerType)]){
        AFNetworkResponseSerializerType type = [request configResponseSerializerType];
        if(type == AFNetworkResponseSerializerType_HTTP){
            responseSerilizer =  [AFHTTPResponseSerializer serializer];
        }
        else if(type == AFNetworkResponseSerializerType_JSON){
            responseSerilizer =  [AFJSONResponseSerializer serializer];
        }
        else if(type == AFNetworkResponseSerializerType_XMLParser){
            responseSerilizer =  [AFXMLParserResponseSerializer serializer];
        }
        
    }
    
    //2.配置响应接受类型accepet类型
    if ([request respondsToSelector:@selector(configResponseAcceptableContentTypes)]) {
        NSSet *set = [request configResponseAcceptableContentTypes];
        if(set != nil)
            responseSerilizer.acceptableContentTypes = [request configResponseAcceptableContentTypes];
    }
    
    return responseSerilizer;
}


#pragma mark - 请求结果处理
- (void)resultProcess:(id)responseDict
                error:(NSError *)error
    isRequireAnalysis:(BOOL)isRequireAnalysis
       sucessResponse:(sucessResponseBlock)sucessBlock
         failResponse:(failResponseBlock)failBlock
{
    if(error != nil)  //请求未连接的失败
    {
        NSString *localMessage = error.userInfo[@"NSLocalizedDescription"];
        [self hanldeErrorMessage:localMessage code:AFNETWORK_NOT_LINK_ERROR_CODE failResponse:failBlock errorInfo:error.userInfo];
        return;
    }else if (responseDict == nil)  //请求失败，返回nil，服务器返回数据错误
    {
        [self hanldeErrorMessage:nil code:AFNETWORK_NOT_LINK_ERROR_CODE failResponse:failBlock errorInfo:error.userInfo];
        return;
    }else  //请求成功
    {
        
        //不需要解析
        if(!isRequireAnalysis){
            if(sucessBlock != nil)
            {
                dispatch_async(self.responseQueue, ^{
                    sucessBlock(responseDict);
                });
            }
            return;
        }
        
        //需要解析
        LZBLog(@"响应返回的数据:%@",responseDict);
        
       _responseModel = [AFExtensionDataConversion modelFromJSONDictionary:responseDict ToModelClass:self.responseClass];
        if(_responseModel == nil)
        {
            [self hanldeErrorMessage:AFNETWORK_SERIALIZER_FAIL_MESSAGE code:AFNETWORK_RESPONSE_SERIALIZER_ERROR_CODE failResponse:failBlock errorInfo:nil];
            return;
        }
        
        //解析完成
        if(_responseModel.success == 1)
        {
            if(sucessBlock != nil)
            {
                dispatch_async(self.responseQueue, ^{
                    sucessBlock(_responseModel);
                });
            }
        }
        else  //请求失败
        {
            [self hanldeErrorMessage:self.responseModel.msg code:self.responseModel.code failResponse:failBlock errorInfo:error.userInfo];
        }
        
    }
}

- (void)hanldeErrorMessage:(NSString *)message code:(NSInteger)code failResponse:(failResponseBlock)failBlock errorInfo:(NSDictionary *)errorInfo
{
    if(message.length == 0)
        message = self.failDefaultMessage;
    NSError *error = [NSError errorWithDomain:[NSString stringWithFormat:@"%@",message] code:code userInfo:errorInfo];
    if(failBlock != nil)
    {
        dispatch_async(self.responseQueue, ^{
            failBlock(error);
        });
    }
}



#pragma mark - pravite

- (NSURLSessionDataTask *)httpBaseRequestWithURL:(NSString *)url
                                      parameters:(NSDictionary *)paramDicts
                               isRequireAnalysis:(BOOL)isRequireAnalysis
                                  HTTPMethodType:(AFNetworkRequestMethod)method
                                  uploadProgress:(uploadProgressBlock)progressBlock
                                  sucessResponse:(sucessResponseBlock)sucessBlock
                                    failResponse:(failResponseBlock)failBlock
{
    return [self dataTaskWithHTTPMethodType:method isRequireAnalysis:isRequireAnalysis URL:url parameters:paramDicts uploadProgress:progressBlock sucessResponse:sucessBlock failResponse:failBlock];
}


- (NSURLSessionDataTask *)dataTaskWithHTTPMethodType:(AFNetworkRequestMethod)method
                               isRequireAnalysis:(BOOL)isRequireAnalysis
                                             URL:(NSString *)URLString
                                      parameters:(NSDictionary *)paramDicts
                                  uploadProgress:(uploadProgressBlock)progressBlock
                                  sucessResponse:(sucessResponseBlock)sucessBlock
                                    failResponse:(failResponseBlock)failBlock
{
    //请求
    NSURLSessionDataTask *dataTask = nil;
    switch (method) {
        case AFNetworkRequestMethod_GET:
            dataTask = [self dataTaskWithHTTPMethod:@"GET" isRequireAnalysis:isRequireAnalysis URL:URLString parameters:paramDicts constructingBodyWithBlock:nil uploadProgress:progressBlock sucessResponse:sucessBlock failResponse:failBlock];
            break;
        case AFNetworkRequestMethod_POST:
        {
            //获取POST请求上传文件操作的block
            dataTask = [self dataTaskWithHTTPMethod:@"POST" isRequireAnalysis:isRequireAnalysis URL:URLString parameters:paramDicts constructingBodyWithBlock:nil uploadProgress:progressBlock sucessResponse:sucessBlock failResponse:failBlock];
        }
            break;
        case AFNetworkRequestMethod_PUT:
            dataTask = [self dataTaskWithHTTPMethod:@"PUT" isRequireAnalysis:isRequireAnalysis URL:URLString parameters:paramDicts constructingBodyWithBlock:nil uploadProgress:progressBlock sucessResponse:sucessBlock failResponse:failBlock];
            break;
        case AFNetworkRequestMethod_HEAD:
            dataTask = [self dataTaskWithHTTPMethod:@"HEAD" isRequireAnalysis:isRequireAnalysis URL:URLString parameters:paramDicts constructingBodyWithBlock:nil uploadProgress:progressBlock sucessResponse:sucessBlock failResponse:failBlock];
            break;
        case AFNetworkRequestMethod_DELETE:
            dataTask = [self dataTaskWithHTTPMethod:@"DELETE" isRequireAnalysis:isRequireAnalysis URL:URLString parameters:paramDicts constructingBodyWithBlock:nil uploadProgress:progressBlock sucessResponse:sucessBlock failResponse:failBlock];
            break;
        case AFNetworkRequestMethod_PATCH:
            dataTask = [self dataTaskWithHTTPMethod:@"PATCH" isRequireAnalysis:isRequireAnalysis URL:URLString parameters:paramDicts constructingBodyWithBlock:nil uploadProgress:progressBlock sucessResponse:sucessBlock failResponse:failBlock];
            break;
            
        default:
            break;
    }
    
    return dataTask;
}


- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
                               isRequireAnalysis:(BOOL)isRequireAnalysis
                                             URL:(NSString *)URLString
                                      parameters:(NSDictionary *)parameters
                       constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block
                                  uploadProgress:(uploadProgressBlock)progressBlock
                                  sucessResponse:(sucessResponseBlock)sucessBlock
                                    failResponse:(failResponseBlock)failBlock
{
    //0.请求处理
    NSMutableURLRequest *mutableRequest = nil;
    NSError * __autoreleasing serializationError = nil;;
    if(block != nil){
        mutableRequest = [self.sessionManger.requestSerializer multipartFormRequestWithMethod:method URLString:URLString parameters:parameters constructingBodyWithBlock:block error:&serializationError];
    }
    else{
        mutableRequest  = [self.sessionManger.requestSerializer requestWithMethod:method URLString:URLString parameters:parameters error:&serializationError];
    }
    
    //开启请求任务
    __weak typeof(self) weakSelf = self;
    
    __block uploadProgressBlock progressInBlock = progressBlock;
    __block sucessResponseBlock sucessResponseInBlock = sucessBlock;
    __block failResponseBlock failResponseInBlock = failBlock;
    __block BOOL isRequireAnalysisInBlock = isRequireAnalysis;
    
    LZBLog(@"request-info:\n{\n requestType:%@\n url:%@\n params:%@\n}",method,URLString,parameters);
    
   NSURLSessionDataTask *dataTask = [self.sessionManger dataTaskWithRequest:mutableRequest uploadProgress:^(NSProgress * _Nonnull uploadProgress) {
        if(progressInBlock != nil){
            dispatch_async(weakSelf.responseQueue, ^{
                progressInBlock(uploadProgress);
            });
        }
    } downloadProgress:^(NSProgress * _Nonnull downloadProgress) {
        if(progressInBlock != nil){
            dispatch_async(weakSelf.responseQueue, ^{
                progressInBlock(downloadProgress);
            });
        }
    } completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
        
        [weakSelf resultProcess:responseObject error:error isRequireAnalysis:isRequireAnalysisInBlock sucessResponse:sucessResponseInBlock failResponse:failResponseInBlock];
        
    }];
    
    return dataTask;
}



@end
